package com.alibaba.datax.plugin.writer.doriswriter;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import java.text.SimpleDateFormat;
import java.util.*;

public class EmrPatientDocCreator {

	private static JSONObject departmentInfo;
	private static final String department = "{\"course_record\":[{\"DEPARTMENT\":\"\"}],\"orders\":[{\"DEPT_NAME\":\"DEPT_CODE\"},{\"EXEC_DEPT_NAME\":\"EXEC_DEPT_CODE\"}],\"chemotherapy\":[{\"CHEMOTHERAPY_DEP\":\"\"}],\"ultrasonic_diagnosis_reports\":[{\"DEPARTMENT\":\"\"}],\"radiotherapy_orders\":[{\"ORGNAME_DIAG\":\"\"}],\"rescue_record\":[{\"DEPARTMENT\":\"\"}],\"death_records\":[{\"DEPARTMENT\":\"\"}],\"pathology_request\":[{\"APPLY_DEPT_NAME\":\"APPLY_DEPT_CODE\"}],"
			+ "\"discharge_summary\":[{\"DEPARTMENT\":\"\"}],\"death_discuss_records\":[{\"DEPARTMENT\":\"\"}],\"medicine_order\":[{\"DEPT_NAME\":\"DEPT_CODE\"}],\"attending_physician_rounds_record\":[{\"DEPARTMENT\":\"\"}],\"nurse_operation\":[{\"EXECUTION_DEPARTMENT\":\"EXECUTION_DEPARTMENT_CODE\"}],\"pathology_reports\":[{\"SUBMITTING_DEPARTMENT\":\"\"}],\"lung_functional_exam\":[{\"DEPARTMENT\":\"\"}],\"inspection_reports\":[{\"SUBMITTING_DEPARTMENT\":\"\"}],\"admissions_records\":[{\"DEPARTMENT\":\"\"}],"
			+ "\"microscopic_exam_reports\":[{\"DEPARTMENT\":\"\"}],\"medical_record_home_page\":[{\"DIS_DEPT_NAME\":\"DIS_DEPT_CODE\"},{\"ADMISS_DEPT_NAME\":\"ADMISS_DEPT_CODE\"}],\"first_course_record\":[{\"DEPARTMENT\":\"\"}],\"other_imaging_exam_diagnosis_reports\":[{\"APPLICATION_DEPARTMENT\":\"\"}],\"electrocardiographic_reports\":[{\"DEPARTMENT\":\"\"}],"
			+ "\"diagnose\":[{\"DIAGNOSTIC_DEPT\":\"DIAGNOSTIC_DEPT_ID\"}],\"visit_info\":[{\"REGISTERED_DEPT\":\"REGISTERED_DEPT_ID\"},{\"ADMISSION_DEPT\":\"ADMISSION_DEPT_ID\"},{\"DISCHARGE_DEPT\":\"DISCHARGE_DEPT_ID\"}],\"triple_test_table\":[{\"EXECUTE_DEPT\":\"EXECUTE_DEPT_CODE\"}],\"pharmacy\":[{\"orders\":[{\"ORDER_DEPT\":\"ORDER_DEPT_CODE\"},{\"EXEC_DEPT\":\"EXEC_DEPT_CODE\"}]}],"
			+ "\"operation\":[{\"records\":[{\"DEPARTMENT\":\"\"}],\"pre_summary\":[{\"DEPARTMENT\":\"\"}],\"post_course_record\":[{\"DEPARTMENT\":\"\"}],\"pre_conference_record\":[{\"DEPARTMENT\":\"\"}]}]}";
	static {
		departmentInfo = JSONObject.parseObject(department);
	}

	public static void supplementPatientInfo(JSONObject patientData) {
		JSONObject patientInfo = patientData.getJSONArray("patient_info").getJSONObject(0);
		JSONArray patient = new JSONArray();

		Set<String> sourceDepartments = new HashSet<>();

		if (patientData.containsKey("specimen_info")) {
			JSONArray specimenInfoArr = patientData.getJSONArray("specimen_info");
			for (Object specimenInfo : specimenInfoArr) {
				JSONObject tmp = (JSONObject) specimenInfo;

				// 来源科室
				if (tmp.containsKey("SOURCE_DEPARTMENT")) {
					sourceDepartments.add(tmp.getString("SOURCE_DEPARTMENT"));
				}

			}
		}

		if (patientData.containsKey("visits")) {
			JSONArray visits = patientData.getJSONArray("visits");

			// 去除无需建索引的组
			supplementVisits(visits);

			JSONArray ALL_VISIT_DEPT = new JSONArray();
			JSONArray ALL_VISIT_DEPT_ID = new JSONArray();
			Map<String, String> map = getDepartmentInfo2(visits);

			for (String s : sourceDepartments) {
				map.put(s, "");
			}

			for (Map.Entry<String, String> entry : map.entrySet()) {
				ALL_VISIT_DEPT.add(entry.getKey());
				ALL_VISIT_DEPT_ID.add(entry.getValue());
			}

			patientInfo.put("ALL_VISIT_DEPT", ALL_VISIT_DEPT);
			patientInfo.put("ALL_VISIT_DEPT_ID", ALL_VISIT_DEPT_ID);

			supplementBirthDateNum(patientInfo);
			supplementAdditionalFields(visits, patientInfo);
			patient.add(patientInfo);
			patientData.put("patient_info", patient);
		}

	}
	
	
	public static Map<String, String> getDepartmentInfo2(JSONArray visits) {
		if (visits == null) {
			return null;
		}
		Map<String, String> map = new HashMap<>();

		visits.forEach(v->{
			JSONObject visit = (JSONObject)v;
			JSONArray visitIndfoArr = visit.getJSONArray("visit_info");
			if (visitIndfoArr != null) {
				visitIndfoArr.forEach(info->{
					JSONObject visitInfo = (JSONObject)info;
					//入院科室
					String dep = visitInfo.getString("ADMISS_DEPT");
					String depId = visitInfo.getString("ADMISS_DEPT_CODE");
					if (dep != null) {
						map.put(dep, depId);
					}
					//离院科室
					dep = visitInfo.getString("DISCHARGE_DEPT");
					depId = visitInfo.getString("DISCHARGE_DEPT_CODE");
					if (dep != null) {
						map.put(dep, depId);
					}
					//挂号科室
					dep = visitInfo.getString("REGISTERED_DEPT");
					depId = visitInfo.getString("REGISTERED_DEPT_CODE");
					if (dep != null) {
						map.put(dep, depId);
					}				
					});
			}
			
		});
		
		return map;
	}
	
	

	public static Map<String, String> getDepartmentInfo(JSONArray visits) {
		// String structure = Util.getJsonFromfile("base/data/DEPARTMENT.json");
		if (visits == null) {
			return null;
		}
		JSONObject structureObj = departmentInfo;
		Iterator<String> structurekeys = structureObj.keySet().iterator();
		Map<String, String> map = new HashMap<>();
		// 循环获取根目录
		while (structurekeys.hasNext()) {
			String key = structurekeys.next();
			JSONArray structureArray = structureObj.getJSONArray(key);

			if (structureArray == null) {
				continue;
			}
			for (int q = 0; q < visits.size(); q++) {
				JSONObject visit = visits.getJSONObject(q);
				// 判断这个对象是否有需要提取的根节点
				if (visit.containsKey(key)) {
					// 获取跟目录子节点（真正的需要取值的obj）
					for (int i = 0; i < structureArray.size(); i++) {
						JSONObject structureObject = structureArray.getJSONObject(i);
						Iterator<String> structKeys = structureObject.keySet().iterator();
						// 获取需要被提取的对象

						while (structKeys.hasNext()) {
							// 获取需要在这个对象提取的具体字段名
							String structKey = structKeys.next();
							// 提取需要被提取的根节点数组
							Object structValue = structureObject.get(structKey);
							JSONArray visitJSONArray = visit.getJSONArray(key);
							
							if (visitJSONArray == null) {
								continue;
							}
							// 循环被提取的根素组
							for (int f = 0; f < visitJSONArray.size(); f++) {
								// 获取被提取的对象
								JSONObject visitData = visitJSONArray.getJSONObject(f);

								if (structValue instanceof String) {
									String depart = null;
									if (visitData.containsKey(structKey)) {
										depart = visitData.getString(structKey);
									}
									String departCode = null;
									if (visitData.containsKey((String) structValue)) {
										departCode = visitData.getString((String) structValue);
									}
									if (depart != null) {
										if (departCode != null) {
											map.put(depart, departCode);
										} else {
											map.put(depart, "");
										}
									}
								} else {
									if (visitData.containsKey(structKey)) {
										JSONArray jsonArray = visitData.getJSONArray(structKey);
										JSONArray structArray = (JSONArray) structValue;
										
										if (structArray == null || jsonArray == null) {
											continue;
										}
										
										for (int j = 0; j < structArray.size(); j++) {

											JSONObject strcObject = structArray.getJSONObject(j);
											Iterator<String> keys = strcObject.keySet().iterator();

											while (keys.hasNext()) {
												for (int n = 0; n < jsonArray.size(); n++) {
													JSONObject obj = jsonArray.getJSONObject(n);													
													if (obj == null) {
														continue;
													}
													String structArrayKey = keys.next();

													String structArrayV = strcObject.getString(structArrayKey);

													String depart = null;
																							
													if (obj.containsKey(structArrayKey)) {
														depart = obj.getString(structArrayKey);
													}
													String departCode = null;
													if (obj.containsKey(structArrayV)) {
														departCode = obj.getString(structArrayV);
													}
													if (depart != null) {
														if (departCode != null) {
															map.put(depart, departCode);
														} else {
															map.put(depart, "");
														}
													}
												}
											}
										}

									}

								}
							}
						}
					}
				}
			}
		}
		return map;
	}

	private static void supplementBirthDateNum(JSONObject patientInfo) {
		if (patientInfo.containsKey("BIRTH_DATE")) {
			String birthDate = patientInfo.getString("BIRTH_DATE");
			if (birthDate != null) {
				birthDate = birthDate.substring(0, 4);
				patientInfo.put("BIRTH_DATE_NUM", Integer.valueOf(birthDate).intValue());
			}
		}
	}

	/**
	 * 去除无需建索引的组
	 * 
	 * @param visits
	 */

	private static void supplementVisits(JSONArray visits) {
	
		visits.forEach((v) -> {
			JSONObject visit = (JSONObject) v;
			if (visit != null) {
				Iterator<String> iterator =  visit.keySet().iterator();
				HashSet<String> removeKeys = new HashSet<>();
				while (iterator.hasNext()) {
					String key = iterator.next();				
					if (visit.get(key) == null) {
						removeKeys.add(key);
					}
				}	
				// 去除空null
				for(String key:removeKeys){
					visit.remove(key);
				}
				
				if (visit.containsKey("inspect_request")) {
					visit.remove("inspect_request");
				}

				// visits.examination_request
				if (visit.containsKey("examination_request")) {
					visit.remove("examination_request");
				}

				// visits.pathology_request 病理申请
				if (visit.containsKey("pathology_request")) {
					visit.remove("pathology_request");
				}

				// visits.operation_request 手术申请
				if (visit.containsKey("operation_request")) {
					visit.remove("operation_request");
				}

				// visits.transfusion_request 输血申请
				if (visit.containsKey("transfusion_request")) {
					visit.remove("transfusion_request");
				}

				// visits.fee 费用
				if (visit.containsKey("fee")) {
					visit.remove("fee");
				}

				// visits.orders 普通医嘱
				// if (visit.containsKey("orders")) {
				// visit.remove("orders");
				// }
			}
		});
	}

	public static void supplementAdditionalFields(JSONArray visitInfos, JSONObject patientInfo) {
		String date = null;
		String dept = null;
		String type = null;
		String bed = null;
		String dDate = null;
		String diagnoseInfo = null;

		long CLINICAL_VISITS_TOTAL_NUM = 0;// 门诊总次数
		long ADMISSIONS_TOTAL_NUM = 0; // 住院总次数
		long HEALTH_EXAM_TOTAL_NUM = 0;// 体检总次数
		long VISITS_TOTAL_NUM = 0; // 总就诊次数
		long OTHER_NUM = 0;// 其他类型的次数
		String VISIT_TYPE = null;
		String VISIT_TYPE_NAME = null;

		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

		try {
			for (int i = 0; i < visitInfos.size(); i++) {
				JSONObject visit = visitInfos.getJSONObject(i);
				JSONArray visits = visit.getJSONArray("visit_info");
				JSONArray diagnoses = visit.getJSONArray("diagnose");
				if (diagnoses != null && diagnoses.size() != 0) {
					for (int l = 0; l < diagnoses.size(); l++) {
						JSONObject diagnose = diagnoses.getJSONObject(l);
						if (diagnose.containsKey("DIAGNOSTIC_DATE")) {
							String tmpDate = diagnose.getString("DIAGNOSTIC_DATE");
							if (dDate == null) {
								dDate = tmpDate;
								diagnoseInfo = supplement(diagnose, "DISEASE");
							} else {
								if (simpleDateFormat.parse(dDate).getTime() < simpleDateFormat.parse(tmpDate)
										.getTime()) {
									dDate = tmpDate;
									diagnoseInfo = supplement(diagnose, "DISEASE");
								}
							}
						} else if (dDate == null) {
							diagnoseInfo = supplement(diagnose, "DISEASE");
						}
					}
				}
				if (visits != null && visits.size() != 0) {
					for (int j = 0; j < visits.size(); j++) {
						JSONObject visit_info = visits.getJSONObject(j);

						if (visit_info.containsKey("VISIT_TYPE_NAME")) {
							VISIT_TYPE_NAME = visit_info.getString("VISIT_TYPE_NAME");
							if ("门诊".equals(VISIT_TYPE_NAME) || "急诊".equals(VISIT_TYPE_NAME)) {
								++CLINICAL_VISITS_TOTAL_NUM;
							} else if ("住院".equals(VISIT_TYPE_NAME)) {
								++ADMISSIONS_TOTAL_NUM;
							} else if ("体检".equals(VISIT_TYPE_NAME)) {
								++HEALTH_EXAM_TOTAL_NUM;
							} else {
								++OTHER_NUM;
							}
						} else if (visit_info.containsKey("VISIT_TYPE")) {
							VISIT_TYPE = visit_info.getString("VISIT_TYPE");

							if ("0".equals(VISIT_TYPE)) {
								++CLINICAL_VISITS_TOTAL_NUM;
							} else if ("1".equals(VISIT_TYPE)) {
								++ADMISSIONS_TOTAL_NUM;
							} else if ("2".equals(VISIT_TYPE)) {
								++HEALTH_EXAM_TOTAL_NUM;
							} else {
								++OTHER_NUM;
							}
						}  

						String tempDate = null;

						if (visit_info.getString("REGISTERED_DATE") != null) {
							if (date != null) {
								tempDate = simpleDateFormat.parse(date).getTime() <= simpleDateFormat
										.parse(visit_info.getString("REGISTERED_DATE")).getTime()
												? visit_info.getString("REGISTERED_DATE") : date;
							} else {
								tempDate = visit_info.getString("REGISTERED_DATE");
							}
						}
						if (visit_info.getString("ADMISSION_DATE") != null) {
							if (tempDate != null) {
								tempDate = simpleDateFormat.parse(tempDate).getTime() <= simpleDateFormat
										.parse(visit_info.getString("ADMISSION_DATE")).getTime()
												? visit_info.getString("ADMISSION_DATE") : tempDate;
							} else {
								if (date != null) {
									tempDate = simpleDateFormat.parse(date).getTime() <= simpleDateFormat
											.parse(visit_info.getString("ADMISSION_DATE")).getTime()
													? visit_info.getString("ADMISSION_DATE") : date;
								} else {
									tempDate = visit_info.getString("ADMISSION_DATE");
								}

							}

						}
						if (tempDate != null && tempDate != date) {
							date = tempDate;
							dept = supplement(visit_info, "REGISTERED_DEPT");

							if (dept == null) {
								dept = supplement(visit_info, "ADMISSION_DEPT");
							}

							if (dept == null) {
								dept = supplement(visit_info, "DISCHARGE_DEPT");
							}

							type = supplement(visit_info, "VISIT_TYPE_NAME");
							bed = supplement(visit_info, "BED_NO");
						}

					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		VISITS_TOTAL_NUM = CLINICAL_VISITS_TOTAL_NUM + ADMISSIONS_TOTAL_NUM + HEALTH_EXAM_TOTAL_NUM + OTHER_NUM;

		patientInfo.put("LAST_VISIT_DIAG", diagnoseInfo);

		if (date != null) {
			patientInfo.put("LAST_VISIT_TIME", date);
		}

		if (dept != null) {
			patientInfo.put("LAST_VISIT_DEPT", dept);
		}

		if (type != null) {
			patientInfo.put("LAST_VISIT_TYPE", type);
		}

		if (bed != null) {
			patientInfo.put("LAST_VISIT_BED", bed);
		}

		patientInfo.put("CLINICAL_VISITS_TOTAL_NUM", CLINICAL_VISITS_TOTAL_NUM);
		patientInfo.put("ADMISSIONS_TOTAL_NUM", ADMISSIONS_TOTAL_NUM);
		patientInfo.put("HEALTH_EXAM_TOTAL_NUM", HEALTH_EXAM_TOTAL_NUM);
		patientInfo.put("OTHER_NUM", OTHER_NUM);
		patientInfo.put("VISITS_TOTAL_NUM", VISITS_TOTAL_NUM);

	}

	private static String supplement(JSONObject dataInfo, String key) {
		String type = null;
		if (dataInfo.containsKey(key)) {
			type = dataInfo.getString(key);

			if (type != null) {
				type = type.trim();
				if (type.isEmpty()) {
					type = null;
				}
			}

		}

		return type;
	}

}
